<template>
	<div ref="container">
		<div style="position: absolute; z-index: 10" class="flex-center w100 h100" v-show="loading">
			<dv-decoration :scale="2">
				<span class="fw" style="font-size: 30px"> {{ percentComplete }}% </span>
			</dv-decoration>
		</div>
		<my-compass :keyType="keyType" />
	</div>
</template>

<script setup name="electron">
import myLabel from '@c/common/my-label.vue'
import { DBUtil } from '@u/indexedDB'
import { useResizeObserver, THREE, GLTFloaderFn, cameraFn, rendererFn, labelRendererFn, CSS3DSprite, compassRotate, keyType } from '@u/threeMinx'

let container = shallowRef(null), // 模型渲染的Demo节点
	renderer, //  WebGLRenderer渲染器
	scene, // 场景
	camera, // 相机
	cameraRender,
	labelRenderer,
	loading = ref(false),
	percentComplete = ref(0)

// 组件宽高
let width, height
useResizeObserver(container, (entries) => {
	width = entries[0].contentRect.width
	height = entries[0].contentRect.height
	camera.aspect = width / height
	camera.updateProjectionMatrix()
	renderer.setSize(width, height)
	labelRenderer.setSize(width, height)
})
// 初始化生命周期
onMounted(() => {
	loading.value = true
	init()
})

onBeforeUnmount(() => {
	cancelAnimationFrame(requestAnimationFrameIndex)
	// 释放显存
	renderer?.dispose()
	// 释放内存
	container = null
	scene = null
})

function init() {
	// 场景
	scene = new THREE.Scene()
	// 相机
	camera = new THREE.PerspectiveCamera(45, width / height, 1, 2000)
	camera.position.set(0, 4, 0)
	cameraRender = cameraFn(camera)
	scene.add(camera)
	renderer = rendererFn(container)
	// 开启阴影渲染
	renderer.shadowMap.enabled = true
	// label
	labelRenderer = labelRendererFn(container)
	// 灯光
	lights()
	// 加载器
	loaderFn()
}
let objects = [],
	model,
	labelObj = new THREE.Group()

function loaderFn() {
	new DBUtil().get(`${import.meta.env.VITE_APP_BASE_BASE || '/'}model/电力监控.glb`).then((blob) => {
		let url = URL.createObjectURL(blob)
		GLTFloaderFn.load(
			url,
			(object) => {
				loading.value = false
				model = object.scene
				scene.add(model)
				objects = model.getObjectByName('墙体').children
				// 添加标签
				scene.add(labelObj)
				labelFn()
				// 添加阴影
				model.getObjectByName('顶部横杆').traverse((child) => {
					if (child.isMesh) child.castShadow = true
				})
				model.getObjectByName('顶部窄墙').traverse((child) => {
					if (child.isMesh) child.castShadow = true
				})
				model.getObjectByName('墙体').traverse((child) => {
					if (child.isMesh) child.receiveShadow = true
				})
				// 顶灯
				for (let i = 1; i < 5; i++) {
					const mc = model.getObjectByName('顶灯').clone()
					mc.position.z = mc.position.z - i * 24
					scene.add(mc)
				}
				// 顶部横杆
				for (let i = 0; i < 31; i++) {
					const mc = model.getObjectByName('顶部横杆').clone()
					mc.position.z = mc.position.z - i * 4
					scene.add(mc)
					const mc2 = model.getObjectByName('顶部横杆').clone()
					mc2.rotateY(Math.PI)
					mc2.position.x = -mc2.position.x
					mc2.position.z = mc2.position.z - i * 4
					scene.add(mc2)
				}
				// 电机1
				for (let i = 0; i < 5; i++) {
					const mc = model.getObjectByName('电机1').clone()
					mc.position.z = mc.position.z - i * 5
					scene.add(mc)
				}
				// 电机2
				for (let i = 0; i < 15; i++) {
					const mc = model.getObjectByName('电机2').clone()
					mc.position.z = mc.position.z - i * 8
					scene.add(mc)
				}
				// 电机3
				for (let i = 0; i < 11; i++) {
					const mc = model.getObjectByName('电机2').clone()
					mc.rotateY(Math.PI)
					mc.position.z = mc.position.z - i * 8 - 32
					mc.position.x = -mc.position.x
					scene.add(mc)
				}
				render()
			},
			(xhr) => {
				if (xhr.lengthComputable) percentComplete.value = Math.round((xhr.loaded / xhr.total) * 100, 2)
			}
		)
	})
}

/**
 * laebl标签
 */
const props = defineProps({
	data: {
		type: Array,
		required: true
	}
})
watch(
	() => props.data,
	(val) => {
		if (model) labelFn(val)
	}
)
function labelFn(val = props.data) {
	labelObj.clear()
	const { x, y, z } = model?.getObjectByName('电机2')?.clone()?.position
	val.forEach((item, i) => {
		const dom = createApp(myLabel, {
			right: false,
			data: {
				name: item.boxName,
				list: [
					{
						title: '电压',
						val: item.voltage,
						suffix: 'V'
					},
					{
						title: '电流',
						val: item.current,
						suffix: 'A'
					}
				]
			},
			callBack: function () {
				console.log(item)
			}
		}).mount(document.createElement('div')).$el
		const pointLabel = new CSS3DSprite(dom)
		pointLabel.position.set(x, y + 2, z - i * 8)
		pointLabel.scale.set(0.015, 0.015, 0.015)
		labelObj.add(pointLabel)
	})
}

/**
 * 灯光
 */
function lights() {
	// 自然光
	scene.add(new THREE.AmbientLight('#a1a1a1', 0.5))
	let light = new THREE.PointLight('#ffffff', 0.6)
	// 投射阴影
	light.castShadow = true
	light.position.set(0, 10.4, -24)
	light.shadow.camera.near = 0.01
	light.shadow.camera.far = 500
	light.shadow.camera.right = 10
	light.shadow.camera.left = -10
	light.shadow.camera.top = 10
	light.shadow.camera.bottom = -10
	// 设置阴影贴图的分辨率
	light.shadow.mapSize.width = 1024
	light.shadow.mapSize.height = 1024
	// 设置阴影贴图模糊度
	light.shadow.radius = 2.5
	light.shadow.bias = -0.0001
	scene.add(light)
}

// 渲染逻辑
let requestAnimationFrameIndex
function render() {
	keyType.value = cameraRender(objects)
	compassRotate(camera)
	renderer?.render(scene, camera)
	labelRenderer?.render(scene, camera)
	requestAnimationFrameIndex = requestAnimationFrame(render)
}
</script>
